
#include "classMidi.h"

#define CS_MIDICHIP 23

midiCustom myMidi; // preinstantiation of myMidi object (declared extern in the .h file)

//initialization of the midi device
//assigned instruments to used chanels
void midiCustom::init(){

  previousActive=false;
  
  // setup the tiny midi chip (note: this is ok to do in an init() function inside the setup function of the main program, but NOT in a constructor called before the setup!). 
  pinMode(CS_MIDICHIP, OUTPUT);
  digitalWrite(CS_MIDICHIP,HIGH);
  delay(200);
   
  // setup midi communication (speed = 31250)
  Serial1.begin(31250);
   
  //setup instruments to chanels [0-15] ('9' is always drum)
  //midiProgramChange (1, );
   
   
  // Assignement of instruments to midi channels in the syntesizer (ex: channel 0 corresponds to instrument 13):
  // NOTE: the first four are percussion instruments, the next four are pitched instruments.
  midiProgramChange (0, 13); //collision chanel - Spot 0
  midiProgramChange (1, 10); //collision chanel - Spot 1
  midiProgramChange (2, 11); //collision chanel - Spot 2
  midiProgramChange (3, 12); //collision chanel - Spot 3
   
  midiProgramChange (4, 4); //pitch bend chanel - Spot 0 //38 better than 39
  midiProgramChange (5, 38); //pitch bend chanel - Spot 1
  midiProgramChange (6, 41); //pitch bend chanel - Spot 2
  midiProgramChange (7, 42); //42 was the value before Sekai ichi //pitch bend chanel - Spot 3
  
  for(int i=0; i<MAXNUMSPOTS; i++){
    previousNote[i]=128;
  }
 
}

void midiCustom::midiTouchWall(int i){
  midiNoteOn(9, 38 + i, 127);
}

void midiCustom::midiCollision(int i, float angle){
  byte note = byte((70.0 * angle / 6.283) + 30);
  midiNoteOn(i, note, 127);
}

void midiCustom::midiCollisionPercussion(int i) {
  midiNoteOn(10, 52, 127); // on channel 10 (percussion), 52 is the "chinese cymbal"
  //midiNoteOn(7, 80, 127); // on channel 10 (percussion), 52 is the "chinese cymbal"
}

void midiCustom::midiPitchAngle(int i, boolean active, float angle){
  if(active){
  byte note = (byte)(int((40.0 * angle / 6.283)/2) *2 + 50);// ATTN: should make notes in a "good" range. In any case, 128 it's considered NOT to be a note. 
  if(i==1) note += 30;
   //byte note = (byte)(50*cos(0.5*angle)+100);
   
    //daito changes :
   /*
    int scale[] = {0,3,7,10};//cMaj
    int currentScale = 1;
    int size = 4;
    int d_num = 40;
    int offsetNote = 60;
    float tmp = angle / 6.283 * (float) d_num;
    byte note = (byte)( scale[(int)tmp % 4] + (int)tmp / 4 + offsetNote);
 */
 
    //if(previousNote[i] <  128){
    //  note = (note + previousNote[i])  >> 1; 
    //}
    midiNoteOn(4+i, note, 120); // +4 because the first 4 are perscussion intruments. 
    midiNoteOff(4+i, previousNote[i]);
    previousNote[i] = note;
  }
  else{
    if(previousNote[i] <  128){ // ATTN: should make notes in a "good" range. In any case, 128 it's considered NOT to be a note. 
    midiNoteOff(4+i, previousNote[i]);
      previousNote[i] = 128;
    }
  }
}

void midiCustom::midiPitchBendAngle(int i, boolean active, float angle){
  if(active){
    if (previousActive!=true) { 
      midiNoteOn(4+2*i, 50 + 20*i, 120);
      previousActive=true;
    }
    
  // midiPitchBend (4+2*i, 0);
   midiPitchBend (4+2*i, int(8192.0*(angle/ 6.283)));
  //  Serial1.print(0xE4+i, BYTE);
  //  Serial1.print(0x0, BYTE);
  //  Serial1.print(byte((126.0 * angle / 6.283)), BYTE);
  }
  else{
    midiNoteOff(4+i, 50 + 10*i);
    previousActive=false;
  }
}

void midiCustom::midiNoteOn (char canal, char nota, char velocity) {
  Serial1.print(0x90 + canal, BYTE);
  Serial1.print(nota, BYTE);
  Serial1.print(velocity, BYTE);
}

void midiCustom::midiNoteOff (char canal, char nota) {
  Serial1.print(0x80 + canal, BYTE);
  Serial1.print(nota, BYTE);
  Serial1.print(0, BYTE);
}

void midiCustom::midiProgramChange (char canal, char programa) {
  Serial1.print(0xC0 + canal, BYTE);
  Serial1.print(programa, BYTE);
}

void midiCustom::midiPitchBend (char canal, int bend) {
  Serial1.print(0xE0 + canal, BYTE);
  Serial1.print((bend + 8192) % 128, BYTE);
  Serial1.print((bend + 8192) / 128, BYTE);
}

void midiCustom::midiAllNoteOff(){
  for(byte i=0; i<16; i++){
    Serial1.print(176 + i, BYTE);
    Serial1.print(123, BYTE);
    Serial1.print(0x0, BYTE);
  }
}

void midiCustom::midiAllSoundOff(){
  for(byte i=0; i<16; i++){
    Serial1.print(176 + i, BYTE);
    Serial1.print(120, BYTE);
    Serial1.print(0x0, BYTE);
  }
}


